use async_trait::async_trait;
use rustcloud_core::{
    ServiceRegistry, ServiceInstance, ServiceResult, ServiceError, RegistryType,
    ServiceWatcher, HealthCheck, ServiceFilter, HealthCheckType
};
use crate::RegistryConfig;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::time::{Duration, SystemTime};
use reqwest::Client;
use tracing::{error, warn, info, debug};

/// Eureka应用实例注册数据结构
#[derive(Serialize, Debug)]
#[serde(rename_all = "camelCase")]
struct EurekaInstanceRegistration {
    instance: EurekaInstance,
}

/// Eureka实例数据结构
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
struct EurekaInstance {
    instance_id: String,
    host_name: String,
    app: String,
    ip_addr: String,
    status: String,
    port: EurekaPort,
    secure_port: EurekaPort,
    home_page_url: String,
    status_page_url: String,
    health_check_url: String,
    data_center_info: DataCenterInfo,
    lease_info: LeaseInfo,
    metadata: HashMap<String, String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    vip_address: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    secure_vip_address: Option<String>,
    country_id: i32,
    is_coordinating_discovery_server: bool,
    last_updated_timestamp: u64,
    last_dirty_timestamp: u64,
    action_type: String,
}

/// Eureka端口信息
#[derive(Serialize, Deserialize, Debug, Clone)]
struct EurekaPort {
    #[serde(rename = "$")]
    port: u16,
    #[serde(rename = "@enabled")]
    enabled: bool,
}

/// 数据中心信息
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
struct DataCenterInfo {
    #[serde(rename = "@class")]
    class: String,
    name: String,
}

/// 租约信息
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
struct LeaseInfo {
    renewal_interval_in_secs: u32,
    duration_in_secs: u32,
    registration_timestamp: u64,
    last_renewal_timestamp: u64,
    eviction_timestamp: u64,
    service_up_timestamp: u64,
}

/// Eureka应用响应
#[derive(Deserialize, Debug)]
struct EurekaApplicationsResponse {
    applications: EurekaApplications,
}

/// Eureka应用列表
#[derive(Deserialize, Debug)]
struct EurekaApplications {
    #[serde(rename = "versions__delta")]
    versions_delta: String,
    #[serde(rename = "apps__hashcode")]
    apps_hashcode: String,
    application: Vec<EurekaApplication>,
}

/// Eureka应用
#[derive(Deserialize, Debug)]
struct EurekaApplication {
    name: String,
    instance: Vec<EurekaInstance>,
}

/// Eureka服务注册中心实现
#[derive(Clone)]
pub struct EurekaRegistry {
    client: Client,
    config: RegistryConfig,
    base_url: String,
    app_name: String,
    heartbeat_tasks: std::sync::Arc<tokio::sync::RwLock<HashMap<String, tokio::task::JoinHandle<()>>>>,
    service_cache: std::sync::Arc<tokio::sync::RwLock<HashMap<String, (Vec<ServiceInstance>, SystemTime)>>>,
    cache_ttl: Duration,
}

impl EurekaRegistry {
    pub fn new(config: RegistryConfig) -> ServiceResult<Self> {
        let client = Client::builder()
            .timeout(Duration::from_secs(30))
            .build()
            .map_err(|e| ServiceError::NetworkError(e.to_string()))?;

        if config.registry_type != RegistryType::Eureka {
            return Err(ServiceError::ConfigurationError(
                format!("Expected Eureka registry type, got: {}", config.registry_type)
            ));
        }

        let base_url = if config.server_addr.is_empty() {
            "http://localhost:8761".to_string()
        } else {
            config.server_addr.clone()
        };
        
        // 从配置或环境变量获取应用名
        let app_name = config.namespace
            .clone()
            .or_else(|| std::env::var("EUREKA_APP_NAME").ok())
            .unwrap_or_else(|| "RUSTCLOUD-SERVICE".to_string());

        Ok(Self {
            client,
            config,
            base_url,
            app_name,
            heartbeat_tasks: std::sync::Arc::new(tokio::sync::RwLock::new(HashMap::new())),
            service_cache: std::sync::Arc::new(tokio::sync::RwLock::new(HashMap::new())),
            cache_ttl: Duration::from_secs(30),
        })
    }

    /// 构建API URL
    fn build_url(&self, endpoint: &str) -> String {
        format!("{}/eureka/apps/{}", self.base_url, endpoint)
    }

    /// 生成实例ID
    fn generate_instance_id(&self, instance: &ServiceInstance) -> String {
        format!("{}:{}:{}", instance.service_id, instance.host, instance.port)
    }

    /// 将ServiceInstance转换为EurekaInstance
    fn to_eureka_instance(&self, instance: &ServiceInstance) -> EurekaInstance {
        let instance_id = self.generate_instance_id(instance);
        let now = SystemTime::now()
            .duration_since(std::time::UNIX_EPOCH)
            .unwrap()
            .as_millis() as u64;

        let app_name = instance.service_id.to_uppercase();
        let base_url = format!("{}://{}", instance.scheme, instance.address());

        EurekaInstance {
            instance_id: instance_id.clone(),
            host_name: instance.host.clone(),
            app: app_name.clone(),
            ip_addr: instance.host.clone(),
            status: if instance.healthy { "UP".to_string() } else { "DOWN".to_string() },
            port: EurekaPort {
                port: instance.port,
                enabled: true,
            },
            secure_port: EurekaPort {
                port: 443,
                enabled: false,
            },
            home_page_url: base_url.clone(),
            status_page_url: format!("{}/actuator/info", base_url),
            health_check_url: format!("{}/actuator/health", base_url),
            data_center_info: DataCenterInfo {
                class: "com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo".to_string(),
                name: "MyOwn".to_string(),
            },
            lease_info: LeaseInfo {
                renewal_interval_in_secs: 30,
                duration_in_secs: 90,
                registration_timestamp: now,
                last_renewal_timestamp: now,
                eviction_timestamp: 0,
                service_up_timestamp: now,
            },
            metadata: instance.metadata.clone(),
            vip_address: Some(app_name.clone()),
            secure_vip_address: Some(app_name),
            country_id: 1,
            is_coordinating_discovery_server: false,
            last_updated_timestamp: now,
            last_dirty_timestamp: now,
            action_type: "ADDED".to_string(),
        }
    }

    /// 从EurekaInstance转换为ServiceInstance
    fn from_eureka_instance(&self, eureka_instance: &EurekaInstance) -> ServiceInstance {
        let mut instance = ServiceInstance::new(
            eureka_instance.app.clone(),
            eureka_instance.ip_addr.clone(),
            eureka_instance.port.port,
            if eureka_instance.secure_port.enabled { "https" } else { "http" }
        );
        
        instance.healthy = eureka_instance.status == "UP";
        instance.metadata = eureka_instance.metadata.clone();
        
        // 从元数据中提取环境信息
        if let Some(environment) = eureka_instance.metadata.get("environment") {
            instance.environment = Some(environment.clone());
        }
        
        if let Some(group) = eureka_instance.metadata.get("group") {
            instance.group = Some(group.clone());
        }
        
        if let Some(cluster) = eureka_instance.metadata.get("cluster") {
            instance.cluster = Some(cluster.clone());
        }
        
        instance
    }

    /// 启动心跳任务
    async fn start_heartbeat(&self, instance: ServiceInstance) {
        let instance_id = self.generate_instance_id(&instance);
        let app_name = instance.service_id.to_uppercase();
        let url = format!("{}/eureka/apps/{}/{}", self.base_url, app_name, instance_id);
        let client = self.client.clone();
        let heartbeat_tasks = self.heartbeat_tasks.clone();
        
        tokio::spawn(async move {
            let instance_id_clone = instance_id.clone();
            let task = tokio::spawn(async move {
                let mut interval = tokio::time::interval(Duration::from_secs(30));
                
                loop {
                    interval.tick().await;
                    
                    match client.put(&url).send().await {
                        Ok(response) if response.status().is_success() => {
                            debug!("Heartbeat sent successfully for instance: {}", instance_id_clone);
                        }
                        Ok(response) => {
                            let status = response.status();
                            warn!("Heartbeat failed for instance: {} - Status: {}", instance_id_clone, status);
                            
                            // 如果实例不存在(404)，需要重新注册
                            if status.as_u16() == 404 {
                                warn!("Instance {} not found in Eureka, may need re-registration", instance_id_clone);
                            }
                        }
                        Err(e) => {
                            error!("Heartbeat error for instance {}: {}", instance_id_clone, e);
                        }
                    }
                }
            });
            
            heartbeat_tasks.write().await.insert(instance_id, task);
        });
    }

    /// 停止心跳任务
    async fn stop_heartbeat(&self, instance: &ServiceInstance) {
        let instance_id = self.generate_instance_id(instance);
        if let Some(task) = self.heartbeat_tasks.write().await.remove(&instance_id) {
            task.abort();
        }
    }

    /// 检查服务缓存
    async fn get_cached_instances(&self, service_name: &str) -> Option<Vec<ServiceInstance>> {
        let cache = self.service_cache.read().await;
        if let Some((instances, cached_time)) = cache.get(service_name) {
            if cached_time.elapsed().unwrap_or(Duration::from_secs(u64::MAX)) < self.cache_ttl {
                return Some(instances.clone());
            }
        }
        None
    }

    /// 更新服务缓存
    async fn update_cache(&self, service_name: &str, instances: Vec<ServiceInstance>) {
        let mut cache = self.service_cache.write().await;
        cache.insert(service_name.to_string(), (instances, SystemTime::now()));
    }

    /// 获取所有应用列表
    async fn get_applications(&self) -> ServiceResult<Vec<String>> {
        let url = format!("{}/eureka/apps", self.base_url);
        
        let response = self.client
            .get(&url)
            .header("Accept", "application/json")
            .send()
            .await
            .map_err(|e| ServiceError::NetworkError(e.to_string()))?;

        if response.status().is_success() {
            let apps_response: EurekaApplicationsResponse = response.json().await
                .map_err(|e| ServiceError::SerializationError(e.to_string()))?;
            
            let services = apps_response.applications.application
                .into_iter()
                .map(|app| app.name)
                .collect();
            
            Ok(services)
        } else {
            let error_text = response.text().await.unwrap_or_default();
            Err(ServiceError::RegistryError(format!("Failed to get applications: {}", error_text)))
        }
    }

    /// 检查Eureka服务器健康状态
    async fn check_eureka_health(&self) -> ServiceResult<bool> {
        let url = format!("{}/eureka/status", self.base_url);
        
        match self.client.get(&url).timeout(Duration::from_secs(5)).send().await {
            Ok(response) if response.status().is_success() => Ok(true),
            _ => Ok(false),
        }
    }

    /// 关闭并清理资源
    pub async fn shutdown(&self) {
        let mut tasks = self.heartbeat_tasks.write().await;
        for (_, task) in tasks.drain() {
            task.abort();
        }
        info!("Eureka registry shutdown completed");
    }
}

#[async_trait]
impl ServiceRegistry for EurekaRegistry {
    async fn register(&self, instance: ServiceInstance) -> ServiceResult<()> {
        let app_name = instance.service_id.to_uppercase();
        let url = self.build_url(&app_name);
        
        let eureka_instance = self.to_eureka_instance(&instance);
        let registration = EurekaInstanceRegistration {
            instance: eureka_instance,
        };

        let response = self.client
            .post(&url)
            .header("Content-Type", "application/json")
            .json(&registration)
            .send()
            .await
            .map_err(|e| ServiceError::NetworkError(e.to_string()))?;

        if response.status().is_success() {
            // 启动心跳任务
            self.start_heartbeat(instance.clone()).await;
            info!("Successfully registered instance to Eureka: {}", instance);
            Ok(())
        } else {
            let error_text = response.text().await.unwrap_or_default();
            Err(ServiceError::RegistryError(format!("Failed to register instance: {}", error_text)))
        }
    }
    
    async fn register_with_metadata(&self, mut instance: ServiceInstance, metadata: HashMap<String, String>) -> ServiceResult<()> {
        // 合并元数据
        instance.metadata.extend(metadata);
        self.register(instance).await
    }
    
    async fn register_with_health_check(&self, instance: ServiceInstance, _health_check: HealthCheck) -> ServiceResult<()> {
        // Eureka使用内置的心跳机制作为健康检查
        // 这里只需要注册实例，健康检查由Eureka服务器管理
        self.register(instance).await
    }

    async fn deregister(&self, instance: ServiceInstance) -> ServiceResult<()> {
        let app_name = instance.service_id.to_uppercase();
        let instance_id = self.generate_instance_id(&instance);
        let url = format!("{}/eureka/apps/{}/{}", self.base_url, app_name, instance_id);

        let response = self.client
            .delete(&url)
            .send()
            .await
            .map_err(|e| ServiceError::NetworkError(e.to_string()))?;

        if response.status().is_success() {
            // 停止心跳任务
            self.stop_heartbeat(&instance).await;
            info!("Successfully deregistered instance from Eureka: {}", instance);
            Ok(())
        } else {
            let error_text = response.text().await.unwrap_or_default();
            Err(ServiceError::RegistryError(format!("Failed to deregister instance: {}", error_text)))
        }
    }

    async fn discover(&self, service_name: &str) -> ServiceResult<Vec<ServiceInstance>> {
        // 检查缓存
        if let Some(cached_instances) = self.get_cached_instances(service_name).await {
            debug!("Returning cached instances for service: {}", service_name);
            return Ok(cached_instances);
        }
        
        let app_name = service_name.to_uppercase();
        let url = format!("{}/eureka/apps/{}", self.base_url, app_name);

        let response = self.client
            .get(&url)
            .header("Accept", "application/json")
            .send()
            .await
            .map_err(|e| ServiceError::NetworkError(e.to_string()))?;

        let status = response.status();
        if status.is_success() {
            let app_response: serde_json::Value = response.json().await
                .map_err(|e| ServiceError::SerializationError(e.to_string()))?;

            let instances = if let Some(app_data) = app_response.get("application") {
                if let Some(instances_array) = app_data.get("instance") {
                    match instances_array {
                        serde_json::Value::Array(arr) => {
                            let mut result = Vec::new();
                            for instance_value in arr {
                                match serde_json::from_value::<EurekaInstance>(instance_value.clone()) {
                                    Ok(eureka_instance) => {
                                        result.push(self.from_eureka_instance(&eureka_instance));
                                    }
                                    Err(e) => {
                                        warn!("Failed to parse Eureka instance: {}", e);
                                    }
                                }
                            }
                            result
                        }
                        serde_json::Value::Object(_) => {
                            // 单个实例的情况
                            match serde_json::from_value::<EurekaInstance>(instances_array.clone()) {
                                Ok(eureka_instance) => {
                                    vec![self.from_eureka_instance(&eureka_instance)]
                                }
                                Err(e) => {
                                    warn!("Failed to parse single Eureka instance: {}", e);
                                    Vec::new()
                                }
                            }
                        }
                        _ => Vec::new(),
                    }
                } else {
                    Vec::new()
                }
            } else {
                Vec::new()
            };

            // 更新缓存
            self.update_cache(service_name, instances.clone()).await;
            
            debug!("Discovered {} instances for service: {}", instances.len(), service_name);
            Ok(instances)
        } else {
            let error_text = response.text().await.unwrap_or_default();
            if status.as_u16() == 404 {
                // 服务不存在，返回空列表
                Ok(Vec::new())
            } else {
                Err(ServiceError::RegistryError(format!("Failed to discover service: {}", error_text)))
            }
        }
    }
    
    async fn discover_with_filter(&self, service_name: &str, filter: ServiceFilter) -> ServiceResult<Vec<ServiceInstance>> {
        let instances = self.discover(service_name).await?;
        let original_count = instances.len();
        let filtered_instances: Vec<ServiceInstance> = instances
            .into_iter()
            .filter(|instance| filter.matches(instance))
            .collect();
            
        debug!("Filtered {} instances for service: {} (original: {})", 
               filtered_instances.len(), service_name, original_count);
        Ok(filtered_instances)
    }

    async fn health_check(&self, service_name: &str) -> ServiceResult<Vec<ServiceInstance>> {
        let instances = self.discover(service_name).await?;
        let healthy_instances = instances.into_iter()
            .filter(|instance| instance.healthy)
            .collect();
        Ok(healthy_instances)
    }
    
    async fn list_services(&self) -> ServiceResult<Vec<String>> {
        self.get_applications().await
    }
    
    async fn registry_health(&self) -> ServiceResult<bool> {
        self.check_eureka_health().await
    }

    async fn watch(&self, _service_name: &str) -> ServiceResult<Box<dyn ServiceWatcher + Send>> {
        // Eureka原生不支持实时事件监听，只能通过轮询实现
        Err(ServiceError::NotImplemented("Eureka does not support real-time event watching".to_string()))
    }
}
